#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "../common/globaldef.h"
#include "../common/bit_rev.h"
#include "../common/ReadFile.h"
#include "../common/globalVai.h"


#define BLOCK_SIZE 128
#define PILOT_NUM 17

extern struct Complex Rhh[BLOCK_SIZE][PILOT_NUM];
int  PN_Len;

struct Complex *Ch_Esti;
struct Complex *Pilot_LS;


//PN_Length = 124;







void Mul_Matrix(struct Complex Matrix1[BLOCK_SIZE][PILOT_NUM],struct Complex Matrix2[PILOT_NUM],struct Complex *Mul_Matrix)
{
	int i,j;
	for (i = 0; i< BLOCK_SIZE;i++)
	{
		Mul_Matrix[i].real  = 0;
		Mul_Matrix[i].imag  = 0;

	}
	for (i=0;i<BLOCK_SIZE;i++)
		for (j=0;j<PILOT_NUM;j++)
			{
				struct Complex ch;
				ch=Mul_complex(Matrix1[i][j],Matrix2[j]);
				Mul_Matrix[i].real+=ch.real;
				Mul_Matrix[i].imag+=ch.imag;
				ch.real=0;
				ch.imag=0;
			}

}

/*Quotient=Diviend/Divisor*/
struct Complex Div_Complex(struct Complex Dividend,struct Complex Divisor)
{
	struct Complex Quotient;
	Quotient.real=(Dividend.real*Divisor.real+Dividend.imag*Divisor.imag)/(Divisor.real*Divisor.real+Divisor.imag*Divisor.imag);
	Quotient.imag=(Dividend.imag*Divisor.real-Dividend.real*Divisor.imag)/(Divisor.real*Divisor.real+Divisor.imag*Divisor.imag);
	return Quotient;

}



void LS(int Start_Index,struct Complex *Symbol)
{
	int i;
	for (i=0;i<(PN_Len-1);i++)
	{
	
		Pilot_LS[i].real = Symbol[8*i+Start_Index].real / Pilot_PN[i];
		Pilot_LS[i].imag = Symbol[8*i+Start_Index].imag / Pilot_PN[i];
	}
	Pilot_LS[PN_Len-1].real = Symbol[Start_Index+FFT_Size-1].real / Pilot_PN[PN_Len-1];
	Pilot_LS[PN_Len-1].imag = Symbol[Start_Index+FFT_Size-1].imag / Pilot_PN[PN_Len-1];
}


void MMSE()
{
	int i,n,block_num;/*Block_num is the number we partition the symbol into*/
	struct Complex Pilot_LS_part[PILOT_NUM];
	block_num=FFT_Size/BLOCK_SIZE;

	for (i=0;i<block_num;i++)
	{
		for (n=0;n<PILOT_NUM;n++)
		{
			Pilot_LS_part[n]=Pilot_LS[16*i+n];
		}

		Mul_Matrix(Rhh,Pilot_LS_part,Ch_Esti+i*BLOCK_SIZE);
		

	}

}

void Restore(int Start_Index,struct Complex *Symbol)
{
	int i;
	for (i=0;i<FFT_Size;i++)
	{
		Symbol[i+Start_Index]=Div_Complex(Symbol[i+Start_Index],Ch_Esti[i]);
	}


}


int ChannelEsti(int Start_Index)
{
	PN_Len = ( int )(FFT_Size /Pilot_Space + 1) ;
	Ch_Esti = (struct Complex *) malloc ( FFT_Size * sizeof (struct Complex));
	if( Ch_Esti  == NULL)
	{
		printf("malloc Ch_Esti for the second training symbol error\n");
		return 0;
	}
	memset(Ch_Esti,0, FFT_Size * sizeof (struct Complex));
	Pilot_LS = (struct Complex *) malloc ( PN_Len * sizeof (struct Complex));
	if( Pilot_LS  == NULL)
	{
		printf("malloc Pilot_LS for the second training symbol error\n");
		return 0;
	}
	memset(Pilot_LS,0, PN_Len * sizeof (struct Complex));
	/*calculate the LS estimation of the pilots */
	LS(Start_Index,Symbol);



	/*calculate the MMSE estimation of all the tones*/
	MMSE();
	
	/*restore the symbol*/
	Restore(Start_Index,Symbol);
	free(Pilot_LS);
	free(Ch_Esti);
	return 1;

}



